
#include "sprite.h"

int HRES;
int VRES;

int x_diff = 100; //difference between the x position of a waterlily
int y_diff = 150; //difference between the y position of a waterlily



char *read_xpm(char *map[], int *wd, int *ht)
{
	  __attribute__((unused)) static char read_xpm_jcard;

	  int width, height, colors;
	  char sym[COLORS];
	  int  col;
	  int i, j;
	  char *pix, *pixtmp, *tmp, *line;
	  char symbol;

  
	  // read width, height, colors
	  if (sscanf(map[0],"%d %d %d", &width, &height, &colors) != 3) {
		printf("read_xpm: incorrect width, height, colors\n");
		return NULL;
	  }
	#ifdef DEBUG
	  printf("%d %d %d\n", width, height, colors);
	#endif
	  if (width > HRES || height > VRES || colors > COLORS) {
		printf("read_xpm: incorrect width, height, colors\n");
		return NULL;
	  }

	  *wd = width;
	  *ht = height;

	  for (i = 0; i < COLORS; i++)
		sym[i] = 0;

	  // read symbols <-> colors 
	  for (i = 0; i < colors; i++) {
		if (sscanf(map[i+1], "%c %d", &symbol, &col) != 2) {
		  printf("read_xpm: incorrect symbol, color at line %d\n", i+1);
		  return NULL;
		}
	#ifdef DEBUG
		printf("%c %d\n", symbol, col);
	#endif
		if (col > COLORS) {
		  printf("read_xpm: incorrect color at line %d\n", i+1);
		  return NULL;
		}
		sym[col] = symbol;
	  }
	  
	  // allocate pixmap memory
	  pix = pixtmp = malloc(width*height);

	  // parse each pixmap symbol line
	  for (i = 0; i < height; i++) {
		line = map[colors+1+i];
	#ifdef DEBUG
		printf("\nparsing %s\n", line);
	#endif
		for (j = 0; j < width; j++) {
		  tmp = memchr(sym, line[j], COLORS);  // find color of each symbol
		  if (tmp == NULL) {
		printf("read_xpm: incorrect symbol at line %d, col %d\n", colors+i+1, j);
		return NULL;
		  }
		  *pixtmp++ = tmp - sym; // pointer arithmetic! back to books :-)
	#ifdef DEBUG
		  printf("%c:%d ", line[j], tmp-sym);
	#endif
		}
	  }

	  return pix;
}



Sprite * create_sprite(char *pic[], int type, int x, int y, Bool visible)
{
	
	Sprite *spriteX;
	

	//allocates memory for the declared SpriteX
	spriteX = (Sprite*) malloc (sizeof(Sprite));
	
	
	if (spriteX == NULL) //couldn't allocate memory
		return NULL;
	
	//map receives de address of the allocated memory where the
    //sprite was read
	spriteX->map = read_xpm(pic, &spriteX->width, &spriteX->height);

	
	//if pixmap is invalid, releases the previously allocated memory and returns NULL
	if (spriteX->map == NULL){
	
		free(spriteX);
		
		return NULL;
	}
	
	
	//if its a normal waterlily in the screen (i.e. not the start or the
	//goal one)
	if (type == NORMAL){
	
		//attribution of the sprite properties, placing it at (x,y) position
		spriteX->x = x;
		spriteX->y = y;
		spriteX->visibility = visible; //the visibility will be random
		spriteX->type = NORMAL;
		
		return spriteX;
	
	}
	//else if its the start waterlily
	else if (type == START){
	
		//attribution of the sprite properties, placing it at (x,y) position
		spriteX->x = BASE_X;
		spriteX->y = BASE_Y + 3 * (BASE_Y * 2); //needs to be placed at the first column of the last row
		spriteX->visibility = visible; //its always visible
		spriteX->type = START;
		
		return spriteX;
	
	}
	//else if its the goal waterlily
	else if (type == GOAL){
	
		//attribution of the sprite properties, placing it at (x,y) position
		spriteX->x = BASE_X + 6 * (BASE_X * 2); //needs to be placed at the last column of the first row
		spriteX->y = BASE_Y; 
		spriteX->visibility = visible; //its always visible
		spriteX->type = GOAL;
		
		return spriteX;
	
	}	
	//else if its the frog (cursor)
	else if (type == FROG){
	
		//attribution of the sprite properties, must be placed over the starting waterlily at the beginning
		spriteX->x = x;
		spriteX->y = y;
		spriteX->visibility = visible; //its always visible
		spriteX->type = FROG;
		
		return spriteX;
	
	}	
	//else if its the golden egg (goal egg)
	else if (type == GOAL_EGG){
	
		//attribution of the sprite properties, placing it over the goal waterlily
		spriteX->x = x;
		spriteX->y = y;
		spriteX->visibility = visible; //its always visible
		spriteX->type = GOAL_EGG;
		
		return spriteX;
	
	}	
	//else if its the a normal egg
	else if (type == EGG){
	
		//attribution of the sprite properties, in a certain position (x,y)
		spriteX->x = x;
		spriteX->y = y;
		spriteX->visibility = visible; //the visibility will be random
		spriteX->type = EGG;
		
		return spriteX;
	
	}
	else {
	
	
		spriteX->x = x;
		spriteX->y = y;
		spriteX->visibility = visible; //the visibility will be random
		spriteX->type = type;
		
		return spriteX;
	}
		
}




int move_sprite(Sprite *base_wlily, int arrow, char *base)
{

	int x, y, pos;
	Sprite *froggie;
	

	
	//the cursor is created only at the start of the game
	if (base_wlily->type == START){
		
		
		//creation of the cursor instance
		froggie = create_sprite(frog, FROG, base_wlily->x + (base_wlily->width / 2), base_wlily->y + (base_wlily->height / 2), VISIBLE);
		
		//update of the cursor coordinates
		froggie->x -= (froggie->width / 2);
		froggie->y -= (froggie->height / 2);
		
		//drawing of the frog at the starting position (center of the
		//start waterlily)
		move_cursor(froggie, base_wlily, 0, 0, base);
		
		return 0;
	}
	
	//according to the key pressed, the cursor is moved to the new position
	//if valid.
	else if (arrow == LEFT_ARROW){

		//next coordinates of the cursor
		x = froggie->x - x_diff;
		y = froggie->y; //there's no vertical movement
			
			
		//checks if the new coordinates are valid
		pos = check_new_position(froggie, base_wlily, x, y, base);
		
		
		if (pos == WITHIN_LIMITS){
		
			move_cursor(froggie, base_wlily, x, y, base);
			
			return 0;
				
		}
		else{ //ver se caso seja um dos cantos, n deixa ir
			
			return -1;
		
		}

		return 0;
		
	}
	
	
	else if (arrow == RIGHT_ARROW){

		//next coordinates of the cursor
		x = froggie->x + x_diff;
		y = froggie->y; //there's no vertical movement
			
			
		//checks if the new coordinates are valid
		pos = check_new_position(froggie, base_wlily, x, y, base);
		
		
		if (pos == WITHIN_LIMITS){
		
			move_cursor(froggie, base_wlily, x, y, base);
			
			return 0;
				
		}
		else{ //ver se caso seja um dos cantos, n deixa ir
			
			return -1;
		
		}
		
		return 0;

		
	}
		
	
		

		
		
/*		
		next_wlily->visibility == VISIBLE
		
		//sets the new coordinates, only the x coordinate is modified
		x -= x_diff;

		
		//checks if sprite is within screen boundaries
		pos = sprite_position(fig, x, y);  //<---ATENCAO VERIFICAR PARA NAO DEIXAR FAZER MOVIMENTOS IMPOSSIVEIS KDO SE ATRIBUI A NOVA COORDENADA EM BAIXO, FAZER LOOP???
			
			
		//if off xx' or yy' axis the sprite keeps it's coordinates
		if (pos == OFF_XX || pos == OFF_YY) 
			return -1;
			
		//if visible and within limits, moves, if possible, to the next waterlily, 
		//according to the keyboard arrow pressed
		else if (pos == WITHIN_LIMITS && fig->visibility == VISIBLE) 
		{
			//erases the previous sprite
			erase_sprite(fig, base);
			
			
			
				
							
				
					
				//draws the sprite at the new coordinates
				draw_sprite(fig, x, y, base);
			
			return 0;
		
		}
		
		if (arrow == RIGTH_ARROW){
		
			//sets the new coordinates, only the x coordinate is modified
			x += x_diff;
				
			//draws the sprite at the new coordinates
			draw_sprite(fig, x, y, base);
			
			return 0;
		
		}
		
		if (arrow == UP_ARROW){
		
			//sets the new coordinates, only the y coordinate is modified
			y -= y_diff;
				
			//draws the sprite at the new coordinates
			draw_sprite(fig, x, y, base);
			
			return 0;
		
		}
		
		if (arrow == DOWN_ARROW){
		
			//sets the new coordinates, only the y coordinate is modified
			y += y_diff;
				
			//draws the sprite at the new coordinates
			draw_sprite(fig, x, y, base);
			
			return 0;
		
		}
	
	}
*/	
	else
		return -1;

}




void destroy_sprite(Sprite *fig, char *base)
{

	if (fig == NULL) //if the sprite doesn't exist, returns
		return;

	erase_sprite(fig, base); //erases sprite from screen
		
	free(fig->map); //releases memory occupied by the pixmap
	free(fig); //releases memory occupied by fig
	
	fig = NULL;

}





void move_cursor(Sprite *cursor, Sprite *lily, int xstep, int ystep, char *base)
{

	//drawing of the cursor at the starting position, at the center 
	//of the start waterlily (xxl)
	if (xstep == 0 && ystep == 0){

		draw_sprite(cursor, cursor->x, cursor->y, base);
				
	}
	//if there is movement, the cursor is erased from the current position, and
	//drawn in the center of the new one
	else if (xstep != 0 && ystep != 0){

		erase_sprite(cursor, base);
		
		//update of the cursor coordinates
		cursor->x = xstep + (lily->width / 2) - (cursor->width / 2);
		cursor->y = ystep + (lily->height / 2) - (cursor->height / 2);
		
		draw_sprite(cursor, cursor->x, cursor->y, base);
	
	}

}




int draw_sprite(Sprite *fig, int x, int y, char *base)
{

	char *pixmap = fig->map; //"pixmap" points to the sprite to put in video memory 
	int col;
	int line = 0;


	fig->x = x;
	fig->y = y;
	

	if (fig->visibility == 1){
	
		while (line < fig->height){
			
			//caso o background nao seja preto (0)
			if ( (pixmap + line * (fig->width)) != 0 ){ 
				
				col = fig->y + line;
								
				memcpy(base + col * HRES + fig->x, pixmap + line * fig->width, fig->width);
			}
					
			line++;
		}
		
		return 0;
		
	}
	
	return 0;
	
}




void draw_fixed_sprites(char *base)
{
	Sprite *start_lily, *goal_lily, *gold_egg;
	int x, y;
	
	
	//drawing of the start waterlily
	start_lily = create_sprite(waterlily_xxl, START, x, y, VISIBLE);
	draw_sprite(start_lily, start_lily->x, start_lily->y, base);
	
	//drawing of the goal waterlily
	goal_lily = create_sprite(waterlily_xxl, GOAL, x, y, VISIBLE);
	draw_sprite(goal_lily, goal_lily->x, goal_lily->y, base);
	
	//drawing of the golden egg over the center of the goal waterlily
	gold_egg = create_sprite(golden_egg, GOAL_EGG, BASE_X + 6 * (BASE_X * 2) + (goal_lily->width / 2),
												   BASE_Y + (goal_lily->height / 2), VISIBLE);
	draw_sprite(gold_egg, gold_egg->x - (gold_egg->width / 2), gold_egg->y - (gold_egg->height / 2), base);
	
	
}




void draw_background(char *base)
{

	int lin, col, x = 0, y = 0;
	

	//painting of the background, pixel by pixel
	for (lin = 0; lin < VRES; lin++){
		
		for (col = 0; col < HRES; col++){
			
			set_pixel(x, y, 11, base);
			
			x++; //increments the x coordinate
		}
		
		x = 0; //reset of the x coordinate
		
		y++; //increments the y coordinate
	}
}



int erase_sprite(Sprite* fig, char *base)
{

	int x = 0;


	while (x < fig->height)
	{
		//if the sprite has green background
		if (fig->type == FROG || fig->type == EGG || fig->type == GOAL_EGG){
		
			//erases sprite from current position, filling memory with color light green (10)
			memset((base + (fig->y + x) * HRES + fig->x), 10, fig->width); 
					
			x++;
		}
		else{
		
			//erases sprite from current position, filling memory with color light cyan (11)
			memset((base + (fig->y + x) * HRES + fig->x), 11, fig->width); 
					
			x++;
		
		}
	}
	
	return 0;
}




int random_num(int num)
{

	int n;

	//initialize random seed
	srand ( time(NULL) );

	//generate number between 0 and num
	n = rand() % num;
	
	return n;

}




int check_new_position(Sprite *cursor, Sprite *base_lily, int x, int y, char *base)
{

	int color;
		
	
	//the coordinates need to be positive to be valid, and can't exceed the screen resolution
	if (x > 0 && y > 0 && x < HRES && y < VRES){
	
		
		//gets the pixel color in the center of the next position
		color = get_pixel(x + (base_lily->width / 2) - (cursor->width / 2), 
						  y + (base_lily->height / 2) - (cursor->height / 2), base);
		
		
		//if the color isn't light cyan (11), then its a waterlily,
		//since the waterlily can have an egg on it
		if (color != LIGHTCYAN)
			return WITHIN_LIMITS; //its within the limits and returns 0
			
		else
			return OFF_LIMITS; //its off the limits and returns -1
			
	}
	
	else
		return OFF_LIMITS;
	
}




void alter_coords(Sprite* fig, int x, int y)
{
	fig->x = x;
	fig->y = y;
}





